﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Web;
using Core;
using Core.Helper;
using Core.Model;
using Core.Msg;

namespace DataServer.Server
{
    /*    实例模式:
        WCF中的并发针对服务而言。而服务实例封装在InstanceContext，所以WCF中的并发最终体现在了InstanceContext中。
        WCF服务实例上下文模式InstanceContextMode又决定服务以何种方法为客户端提供服务。
        PerSession：每次会话都是使用同一个服务实例
        PerCall：每次调用都创建新的服务实例对象
        Single：所有服务都是用同一个服务实例对象，相当于所有客户端代理都使用服务端同一个静态服务实例对象为其服务
        默认情况下，InstanceContextMode默认为PerSession
        并发部分:
        服务通过ServiceBehaviorAttribute的ConcurreceMode属性定义了三种不同的并发模型：
        Single:封装服务实例的InstanceContext某时刻只处理一个客户端请求，其他的请求会被放入请求队列中等待处理。
              如果多个客户端对服务并发访问，这些服务最终在服务端也是通过串行化进行处理。如果之前的请求处理完毕，
               队列中的第一个请求会被处理。它的实现是对InstanceContext继承自CommucationObject中ThisLock
        Reentrant:该模式与Single一样，某时刻只能处理一个客户端请求。与Single不同的是:如果在处理 请求A时，
                某时刻服务端回调客户端，此时服务可继续处理下一个请求B。当回调客户端完成返回服务端，如果B请求没有处理完，
               则A请求需要继续等待直至请求B释放锁，此时如果A能获取到锁，则它的请求被继续执行。
        Multiple:在该模式下，封装服务实例的一个InstanceContext能同时处理多个请求。
        默认情况下，ConcurrencyMode 为Single。*/
    //[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    public class ControlService:IControlService
    {
        private readonly object _synObj = new object();
        #region 公用

        private string GetAddress()
        {
            try
            {
                OperationContext context = OperationContext.Current;
                //获取传进的消息属性
                MessageProperties properties = context.IncomingMessageProperties;
                //获取消息发送的远程终结点IP和端口
                RemoteEndpointMessageProperty endpoint = properties[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;
                if (endpoint == null)
                    return "";
                return $"{endpoint.Address}";
            }
            catch
            {
            }
            return "";
        }

        #endregion

        #region 设备操作

        public IEnumerable<Channel> GetAllChannel()
        {
            return AppManager.ChannelDao.GetEntities();
        }

        public Channel GetChannel(string id)
        {
            return AppManager.ChannelDao.GetEntityById(id);
        }

        public IEnumerable<Device> GetDeviceByChannelId(string chlid)
        {
            var devs = AppManager.DeviceDao.GetDevicesByChlId(chlid);
            if (devs != null)
            {
                foreach (var sss in devs)
                {
                    sss.DeviceType = AppManager.DeviceTypeDao.GetEntityById(sss.DeviceTypeId);
                }
                return devs;
            }
            return null;
        }

        public IEnumerable<Device> GetDeviceByIds(string devIds) // 逗号分割id
        {
            return AppManager.DeviceDao.GetDevicesByIds(devIds);
        }

        public Device GetDevice(string devid)
        {
            return AppManager.DeviceDao.GetEntityById(devid);
        }

        public IEnumerable<DataItem> GetDataItemByDeviceId(string devid, bool storageFilter)
        {
            return AppManager.DataItemDao.GetDataItemsByDevId(devid, storageFilter);
        }

        public DataItem GetDataItem(string dataid)
        {
            return AppManager.DataItemDao.GetEntityById(dataid);
        }

        public DataItem GetDataItemByRcId(string rcid)
        {
            return AppManager.RemoteItemDao.GetDataItemByRcId(rcid);
        }

        public IEnumerable<DeviceType> GetAllDeviceType()
        {
            return AppManager.DeviceTypeDao.GetEntities();
        }

        public IEnumerable<Operation> GetOperationByDeviceType(string id)
        {
            return AppManager.OperationDao.GetOperationByDevType(id);
        }
        /***************************设备分类管理****************************/
        public IEnumerable<DeviceCategory> GetAllCategories()
        {
            return AppManager.DeviceCategoryDao.GetEntities();
        }
        public IEnumerable<DeviceCategory> GetCatgoryWithDevices()
        {
            return AppManager.DeviceCategoryDao.GetCatgoryWithDevices();
        }
        public bool SaveCategroy(IEnumerable<DeviceCategory> categories)
        {
            if (categories == null)
            {
                return false;
            }
            return AppManager.DeviceCategoryDao.SaveEntities(categories.ToList());
        }
        public List<DataItem> GetReportDataByDevIds(string devIds)
        {
            return AppManager.DataItemDao.GetReportDataByDevIds(devIds);
        }
        #endregion

        #region 执行命令 遥控

        public OperateResult ExcuteCommand(string chlid, string devid, string operid, string paras,int timeout)
        {
            return AppManager.ExcuteCommand(chlid, devid, operid, paras, timeout);
        }

        public OperateResult RemoteControlCommand( string rcId, bool on, int timeout)
        {
            lock (_synObj)
            {
                return AppManager.RemoteControlCommand(rcId, on, timeout);
            }
        }

        public bool UpdateAlarmWin(string rcId, bool @on)
        {
            return AppManager.RemoteItemDao.UpdateAlarmWin(rcId, on);
        }

        public List<RemoteItem> GetRemoteItems()
        {
            return AppManager.RemoteItemDao.GetEntities();
        }

        public RemoteItem GetRemoteItem(string id)
        {
            return AppManager.RemoteItemDao.GetEntityById(id);
        }

        /* public OperateResult ExcuteCommandWithParas(string chlid, string devid, string operid, string paras)
        {
            return AppManager.ExcuteCommand(chlid, devid, operid, paras);
        }*/



        #endregion

        #region 用户信息

        public IEnumerable<User> GetAllUsers()
        {
            var list = AppManager.UserDao.GetEntities().ToArray();
            return list;
        }

        public OperateResult Login(string name, string password)
        {
            OperateResult result = AppManager.Login(name, password);
            if (result.Result == eResult.S_OK)
            {
                string ip = GetAddress();
                if (string.IsNullOrEmpty(ip))
                {
                    return new OperateResult(eResult.S_FAILED, "获取登录客户端信息失败!");
                }
                string cookie = EncryptHelper.EncryptDES(ip, "12332156");
                if (WebOperationContext.Current != null)
                    WebOperationContext.Current.OutgoingResponse.Headers[
                        HttpResponseHeader.SetCookie] = cookie;
                else
                    return new OperateResult(eResult.S_FAILED, "获取登录客户端信息失败!");
            }
            return result;
        }

        public OperateResult Logout(string name)
        {
            return AppManager.Logout(name);
        }

        public OperateResult UpdateUser(User user)
        {
            return AppManager.UpdateUser(user);
        }

        public OperateResult RegisterUser(User user)
        {
            return AppManager.RegisterUser(user);
        }

        public OperateResult DeleteUser(User user)
        {
            return AppManager.DeleteUser(user);
        }

        public List<Right> GetAllRights()
        {
            return AppManager.GetAllRights();
        }

        public List<Right> GetUserRights(string userId)
        {
            return AppManager.GetUserRights(userId);
        }

        public bool UpdateUserRights(string userId, string rights)
        {
            return AppManager.UpdateUserRights(userId, rights);
        }

        public List<string> GetUserDevices(string userId)
        {
            return AppManager.GetUserDeviceIds(userId);
        }

        public bool UpdateUserDevices(string userId, string deviceIds)
        {
            return AppManager.UpdateUserDevices(userId, deviceIds);
        }

        public bool UserOwnDevice(string userId, string devId)
        {
            return AppManager.RightDao.UserOwnDevice(userId, devId);
        }

        public List<OperRecord> GetUserOperation(string user, string from = "", string to = "")
        {
            DateTime val;
            DateTime? fromTime = null, toTime = null;
            if (DateTime.TryParse(from, out val))
            {
                fromTime = val;
            }
            if (DateTime.TryParse(to, out val))
            {
                toTime = val;
            }

            return AppManager.GetOperRecords(user, fromTime, toTime);
        }

        public bool AddUserOperation(OperRecord record)
        {
            return AppManager.AddUserOperation(record);
        }

        #endregion

        #region 通道方法操作

        public Dictionary<string, List<string>> GetChannelMethods(string chlid)
        {
            return AppManager.GetChannelMethods(chlid);
        }

        public OperateResult InvokeChannelMethod(string chlid, string method, string paras, int timeout)
        {
            return AppManager.InvokeMethod(chlid, method, paras, timeout);
        }



        #endregion

        #region 获取历史数据

        public List<HisDataMsg> GetMinuteLatestHisData(int num,int minute, string ids, string dateFormat)
        {
            List<string> idList = ids.Split(',').ToList();
            var result =  AppManager.HisDataDao.GetMinuteReport(DateTime.Now, num, minute, idList);
            if (result != null && !string.IsNullOrEmpty(dateFormat))
            {
                foreach (HisDataMsg dataMsg in result)
                {
                    dataMsg.Time = dateFormat;
                }
            }
            return result;
        }
        public List<HisDataMsg> GetMinuteHisData(string dateFrom, string dateTo, string ids, string dateFormat)
        {
            DateTime from, to;
            if (!DateTime.TryParse(dateFrom, out from) || !DateTime.TryParse(dateTo, out to))
            {
                return null;
            }
            List<string> idList = ids.Split(',').ToList();
            var result = AppManager.HisDataDao.GetMinuteReport(from,to, idList);
            if (result != null && !string.IsNullOrEmpty(dateFormat))
            {
                foreach (HisDataMsg dataMsg in result)
                {
                    dataMsg.Time = dateFormat;
                }
            }
            return result;
        }
        public List<HisDataMsg> GetMinuteHisData1(string date, string ids)
        {
            DateTime datetime;
            if (!DateTime.TryParse(date, out datetime))
            {
                return null;
            }
            var result = AppManager.HisDataDao.GetMinuteReport(datetime, ids);
            return result;
        }

        public List<HisDataMsg> GetHourLatestHisData(int num, string ids, string dateFormat)
        {
            List<string> idList = ids.Split(',').ToList();
            var result = AppManager.HisDataDao.GetHourReport(DateTime.Now, num, idList);
            if (result != null && !string.IsNullOrEmpty(dateFormat))
            {
                foreach (HisDataMsg dataMsg in result)
                {
                    dataMsg.Time = dateFormat;
                }
            }
            return result;
        }

        public List<HisDataMsg> GetHourHisData(string date, int num, string ids, string dateFormat)
        {
            DateTime dateTime;
            if (string.IsNullOrEmpty(date))
            {
                dateTime = DateTime.Now;
            }
            else
            {
                dateTime = DateTime.Parse(date);
            }
            List<string> idList = ids.Split(',').ToList();
            var result = AppManager.HisDataDao.GetHourReport(dateTime, num, idList);
            if (result != null && !string.IsNullOrEmpty(dateFormat))
            {
                foreach (HisDataMsg dataMsg in result)
                {
                    dataMsg.Time = dateFormat;
                }
            }
            return result;
        }

        public List<HisDataMsg> GetDayHisData(string toDate, int num,string ids, string dateFormat)
        {
            DateTime dateTime;
            if (string.IsNullOrEmpty(toDate))
            {
                dateTime = DateTime.Now;
            }
            else
            {
                dateTime = DateTime.Parse(toDate);
            }
            List<string> idList = ids.Split(',').ToList();
            var result = AppManager.HisDataDao.GetDayReport(dateTime, num, idList);
            if (result != null && !string.IsNullOrEmpty(dateFormat))
            {
                foreach (HisDataMsg dataMsg in result)
                {
                    dataMsg.Time = dateFormat;
                }
            }
            return result;
        }

        public List<HisDataMsg> GetMonthHisData(string date,int num, string ids, string dateFormat)
        {
            DateTime dateTime;
            if (string.IsNullOrEmpty(date))
            {
                dateTime = DateTime.Now;
            }
            else
            {
                dateTime = DateTime.Parse(date);
            }
            List<string> idList = ids.Split(',').ToList();
            var result = AppManager.HisDataDao.GetMonthReport(dateTime, num, idList);
            if (result != null && !string.IsNullOrEmpty(dateFormat))
            {
                foreach (HisDataMsg dataMsg in result)
                {
                    dataMsg.Time = dateFormat;
                }
            }
            return result;
        }

        public List<HisStatData> GetStatisticReport(int type, string date, string ids)
        {
            DateTime dateTime;
            if (string.IsNullOrEmpty(date))
            {
                dateTime = DateTime.Now;
            }
            else
            {
                dateTime = DateTime.Parse(date);
            }
            List<string> idList = ids.Split(',').ToList();
            return AppManager.HisDataDao.GetStatisticReport(type,dateTime, idList);
        }

        public List<HisCmpData> GetCmpReport(int type, string date, string ids)
        {
            DateTime dateTime;
            if (string.IsNullOrEmpty(date))
            {
                dateTime = DateTime.Now;
            }
            else
            {
                dateTime = DateTime.Parse(date);
            }
            List<string> idList = ids.Split(',').ToList();
            return AppManager.HisDataDao.GetCmpReport(type,dateTime, idList);
        }

        #endregion

        #region 获取/修改实时数据

        public List<RealTimeData> GetRealTimeData(string ids)
        {
            List<string> idList = ids.Split(',').ToList();
            return AppManager.GetRealTimeDatas(idList);
        }

        public OperateResult ModifyData(string devId,string dataId,double value,int timeout)
        {
            return AppManager.ModifyDataValue(devId, dataId, value, timeout);
        }

        public OperateResult ModifyDataEx(string chlId,string devId, string dataId, double value, int timeout)
        {
            return AppManager.ModifyDataValue(chlId,devId, dataId, value, timeout);
        }

        public RxTxCommand DirectSendstrCommand(string chlId, string devId, string content, int timeout)
        {
            return AppManager.DirectSendContent(chlId, devId, content, timeout);
        }

        public RxTxCommand DirectSendbyteCommand(string chlId, string devId, byte[] content, int timeout)
        {
            return AppManager.DirectSendContent(chlId, devId, content, timeout);
        }

        #endregion

        #region 页面处理

        public List<PageInfo> GetAllPages()
        {
            return AppManager.PageInfoDao.GetEntities();
        }

        public PageInfo GetPageById(string id)
        {
            return AppManager.PageInfoDao.GetEntityById(id);
        }

        public PageInfo GetHomePage()
        {
            return AppManager.PageInfoDao.GetHomePage();
        }

        public bool SetHomePage(string pageId)
        {
            return AppManager.PageInfoDao.SetHomePage(pageId);
        }

        public PageInfo GetPageByName(string name)
        {
            return AppManager.PageInfoDao.GetEntityByName(name);
        }
        public bool SavePages(List<PageInfo> pageInfos)
        {
            return AppManager.PageInfoDao.SaveEntities(pageInfos);
        }

        public bool SavePage(PageInfo pageInfo)
        {
            return AppManager.PageInfoDao.InsertOrUpdateEntity(pageInfo);
        }
        public bool DeletePage(PageInfo pageInfo)
        {
            return AppManager.PageInfoDao.DeleteEntity(pageInfo);
        }
        public bool DeletePageById(string pageId)
        {
            return AppManager.PageInfoDao.DeleteEntityById(pageId);
        }

        public List<PageResource> GetAllResource()
        {
            return AppManager.ResourceDao.GetAllResources();
        }

        public bool UploadResource(PageResource resource)
        {
            if (resource == null || string.IsNullOrEmpty(resource.Id) || resource.Content == null) return false;
            return AppManager.ResourceDao.InsertOrUpdateEntity(resource);
        }

        public bool UploadResources(List<PageResource> resources)
        {
            if (resources == null ||  resources.Count==0) return false;
            return AppManager.ResourceDao.InsertEntities(resources);
        }

        public PageResource DownLoadResource(string id)
        {
            if (string.IsNullOrEmpty(id)) return null;
            return AppManager.ResourceDao.GetEntityById(id);
        }

        public bool DeleteResource(string id)
        {
            if (string.IsNullOrEmpty(id)) return false;
            return AppManager.ResourceDao.DeleteById(id);
        }

        #endregion

        #region 脚本信息

        public List<ScriptInfo> GetAllScripts()
        {
            return AppManager.ScriptInfoDao.GetEntities();
        }
        public List<ScriptInfo> GetGlobalScripts()
        {
            return AppManager.ScriptInfoDao.GetGlobalScripts();
        }
        public ScriptInfo GetScriptInfo(string scriptId)
        {
            return AppManager.ScriptInfoDao.GetEntityById(scriptId);
        }
        public ScriptInfo GetScriptInfoByPageId(string pageId)
        {
            return AppManager.ScriptInfoDao.GetEntityByPageId(pageId);
        }
        public bool SaveScripts(List<ScriptInfo> scriptInfos)
        {
            return AppManager.ScriptInfoDao.SaveEntities(scriptInfos);
        }

        public bool SaveScript(ScriptInfo scriptInfo)
        {
            return AppManager.ScriptInfoDao.InsertOrUpdateEntity(scriptInfo);
        }

        public bool DeleteScript(ScriptInfo scriptInfo)
        {
            return AppManager.ScriptInfoDao.DeleteEntity(scriptInfo);
        }

        public bool DeleteScriptById(string id)
        {
            return AppManager.ScriptInfoDao.DeleteEntityById(id);
        }

        public bool DeleteScriptByPageId(string pageId)
        {
            return AppManager.ScriptInfoDao.DeleteEntityByPageId(pageId);
        }


        #endregion

        #region 事件处理

        public List<Event> GetEvents(EventType type, EventLevel level, string from = "", string to = "")
        {
            DateTime val;
            DateTime? fromTime = null, toTime = null;
            if (DateTime.TryParse(from, out val))
            {
                fromTime = val;
            }
            if (DateTime.TryParse(to, out val))
            {
                toTime = val;
            }
            return AppManager.GetEvents(type, level, null, fromTime, toTime);
        }

        public List<Event> GetEventsWithConfirm(EventType type, EventLevel level, bool isConfirm, string from = "", string to = "")
        {
            DateTime val;
            DateTime? fromTime=null, toTime=null;
            if (DateTime.TryParse(from, out val))
            {
                fromTime = val;
            }
            if (DateTime.TryParse(to, out val))
            {
                toTime = val;
            }
            return AppManager.GetEvents(type, level, isConfirm, fromTime, toTime);
        }
        public bool ConfirmEvent(string ids, string man)
        {
            if (string.IsNullOrEmpty(ids)) return false;
            string[] items = ids.Split(',');
            return AppManager.ConfirmEvent(items, man);
        }

        #endregion

        #region 用户操作记录

        

        #endregion
    }
   
}
